package com.zdxlz.manweb.utils;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Description：多线程插入数据
 * * 该程序展示了如何使用多线程将大量数据插入到数据库中。
 *  * 它创建了一个包含100000条数据的列表，然后使用10个线程将这些数据分批插入到数据库中。
 *  * 每个线程处理一批数据，每批数据包含1000条记录。
 * @Author： fengcheng
 * @Date： 2024/11/5 18:31
 */
public class MultiThreadInsertData {

    public static void main(String[] args) {
        // 创建一个包含10万条数据的集合
        List<Data> dataList = new ArrayList<>(100000);
        for (int i = 0; i < 100000; i++) {
            dataList.add(new Data(i, "Data " + i));
        }

        // 使用固定大小的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        // 定义一个批次大小
        int batchSize = 1000;

        // 计算需要的批次数量
        int numBatches = (int) Math.ceil((double) dataList.size() / batchSize);

        // 用于存储CompletableFuture的列表
        List<CompletableFuture<Void>> futures = new ArrayList<>();

        // 分批处理数据
        for (int i = 0; i < numBatches; i++) {
            int start = i * batchSize;
            int end = Math.min(start + batchSize, dataList.size());
            List<Data> batch = dataList.subList(start, end);

            // 提交任务到线程池
            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                try {
                    System.out.println("开始并发了");
                    insertBatch(batch);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }, executorService);
            futures.add(future);
        }

        // 等待所有任务完成
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();

        // 关闭线程池
        executorService.shutdown();
    }

    private static void insertBatch(List<Data> batch) throws InterruptedException {
        Thread.sleep(5000);
        System.out.println("Batch size: " + batch.size());
    }

    static class Data {
        private int id;
        private String name;

        public Data(int id, String name) {
            this.id = id;
            this.name = name;
        }

        public int getId() {
            return id;
        }

        public String getName() {
            return name;
        }
    }
}
